/*
 *  Copyright (c) 2012 Alaitsev I.K.
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 *  and associated documentation files (the "Software"), to deal in the Software without restriction,
 *  including without limitation the rights to use, copy, modify, merge, publish, distribute,
 *  sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all copies or
 *  substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
 *  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 *  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include "core_visualisation_cylinder.h"

#include <algorithm>

#include <QDebug>
#include <QGraphicsEllipseItem>
#include <QResizeEvent>

#include "core.h"

#include "common_defines_and_includes.h"

Core_Visualisation_Cylinder::Core_Visualisation_Cylinder(QWidget *parent) :
  #ifdef QCUSTOMPLOT_BASED
  QCustomPlot (parent),
  #endif
  _core               (nullptr),
  #ifdef QCUSTOMPLOT_BASED
  _external_electrode (addGraph(xAxis, yAxis)),
  _internal_electrode (addGraph(xAxis, yAxis))
  #endif
  {
#ifdef QCUSTOMPLOT_BASED
  for (int i = 0;
       i < 12;
       ++i) {
    _equipotential_lines .append(new QCPCurve(xAxis, yAxis));
    addPlottable(_equipotential_lines[i]);
  }
//  for (int i = 0;
//       i < 101;
//       ++i) {
//    _l .append(new QCPCurve (xAxis, yAxis));
//    addPlottable(_l[i]);
//  }
#endif
}

Core *Core_Visualisation_Cylinder::core(Core *in_new_value) {
  if (in_new_value != nullptr) {
    _core = in_new_value;

    connect((QObject*)(_core),
            SIGNAL(system_parameters_changed ()),
            this,
            SLOT  (update_visualisation      ()));

    update_visualisation();
  }

  return _core;
}

void Core_Visualisation_Cylinder::update_visualisation() {
  /*
   *  Следует либо переписать эту функцию, расширив её интерфейс, а так же сам класс визуализатора и
   *  центральный класс моделирования (Core), либо написать отдельную функцию/класс-функтор для
   *  обновления визуализации в процессе моделирования.
  */
  if (_core == nullptr) {
    return;
  }
#ifdef QCUSTOMPLOT_BASED
  Core::core_eqp_l_array lines = _core ->equipotential_lines (10, 100);
  int i = 0;
  double max_y = -1;
  double max_x = -1;
  double min_y = 1;
  double min_x = 1;
  QVector <QVector <double> > lx;
  QVector <QVector <double> > ly;
  lx .resize(101);
  ly .resize(101);
  for (auto arr : lines) {
    QVector <double> x;
    QVector <double> y;
    QVector <double> f;
    int j = 0;
    for (QPointF p : arr) {
      x .append(cos (p .x()) * (p .y() + _core ->_internal_electrode_radius_no_grade));
      y .append(sin (p .x()) * (p .y() + _core ->_internal_electrode_radius_no_grade));
      f .append(p .x());
      if (sin (p .x()) * (p .y() + _core ->_internal_electrode_radius_no_grade) > max_y) {
        max_y = sin (p .x()) * (p .y() + _core ->_internal_electrode_radius_no_grade);
      }
      if (cos (p .x()) * (p .y() + _core ->_internal_electrode_radius_no_grade) > max_x) {
        max_x = cos (p .x()) * (p .y() + _core ->_internal_electrode_radius_no_grade);
      }
      if (sin (p .x()) * (p .y() + _core ->_internal_electrode_radius_no_grade) < min_y) {
        min_y = sin (p .x()) * (p .y() + _core ->_internal_electrode_radius_no_grade);
      }
      if (cos (p .x()) * (p .y() + _core ->_internal_electrode_radius_no_grade) < min_x) {
        min_x = cos (p .x()) * (p .y() + _core ->_internal_electrode_radius_no_grade);
      }
      lx [j] .append(x[j]);
      ly [j] .append(y[j]);
      ++j;
    }
//    _equipotential_lines [i] ->setData(f, x, y);
    ++i;
  }

//  for (int i = 0;
//       i < lx .size();
//       ++i) {
//    _l [i] ->setData(lx[i],ly[i]);
//  }
  xAxis ->setRange(min_x + .1*min_x, max_x + .1*max_x);
  yAxis ->setRange(min_y + .1*min_y, max_y + .1*max_y);

  Core::lines_pack_cylinder lines_ = _core ->equipotential_lines_cylinder_coordinates_analitic_solution (10,
                                                                                                        100);
  for (int i = 0;
       i < lines_ ._eq_p .size ();
       ++i) {
    _equipotential_lines [i] ->setData (lines_ ._eq_p [i] ._fis,
                                        lines_ ._eq_p [i] ._xs,
                                        lines_ ._eq_p [i] ._ys);
  }

  replot();
#endif
}

void Core_Visualisation_Cylinder::resizeEvent(QResizeEvent *event) {
#ifdef QCUSTOMPLOT_BASED
  QCustomPlot::resizeEvent(event);
  rescaleAxes();
#endif
}
